#include <stdio.h>
#include <stdbool.h>
#include "subcatch.h"
#include "sc_error.h"
#include "utlist.h"

struct sc_subhier *map_root;

int sc_sub(struct sc_context *context, const char *sub)
{
    return sub__add(context,sub,0,&map_root);

}

int sc_pub(struct sc_context *context, const char *topic,struct sc_msg* msg)
{
    sub__messages_queue(context->id,topic,msg);
}

int sc_init()
{
    map_root = NULL;
	sub_add_heir_entry(NULL, &map_root, "", 0);
}


int sub__add(struct sc_context *context, const char *sub,  int options, struct sc_subhier **root)
{
    int rc = 0;
    sc_subhier *hier;
    char* local_sub;
    char**topics;
    size_t topiclen;
    const char* sharename = NULL;

    if(root == NULL || *root == NULL)
    {
        return SC_ERROR;
    }
    if(sub == NULL)
    {
        return SC_ERROR;
    }
    rc = sub_topic_tokenise(sub,&local_sub,&topics,&sharename);
    if(rc) return rc;

    topiclen = strlen(topics[0]);
    //在root 为根的hash 表里查找topics[0] 的hier
    HASH_FIND(hh,*root,topics[0],topiclen,hier);
    if(!hier)
    {
        //找不到就直接将topic[0] 放入hash表，
        hier = sub_add_heir_entry(NULL, root, topics[0],(uint16_t)topiclen);
        if(!hier)
        {
            free(local_sub);
            free(topics);
            return SC_ERR_NOMEM;
        }

    }
    //找到节点
    rc = sub_add_context(context,sub,options,hier,topics,sharename);
    free(local_sub);
    free(topics);
   return SC_OK;
}

/*
func: 将topic 转换成hier节点，放入hash 中,并指明parent 等索引信息
parent: 父节点
sibling 兄弟节点
topic : 当前节点
len 当前节点长度
return: 返回生成的节点
*/
struct sc_subhier* sub_add_heir_entry(struct sc_subhier *parent, struct sc_subhier **sibling, const char* topic,  uint16_t len)
{
    struct sc_subhier *child;
    child = calloc(1,sizeof(struct sc_subhier));
    if(!child)
    {
        return NULL;
    }
    child->parent = parent;
    child->topic_len = len;
    child->topic = strdup(topic);
    if(!child->topic)
    {
        child->topic_len = 0;
        free(child);
        printf("Error: out of memery");
        return NULL;
    }
    HASH_ADD_KEYPTR(hh,*sibling,child->topic,child->topic_len,child);
    return child;
}

static int sub_add_context(struct sc_context *context,const char *topic_filter, int options, struct sc_subhier *subhier, char *const *const topics, const char *sharename)
{
    struct sc_subhier * branch;
    int topic_index = 0;
    size_t topiclen;
	struct sc_subleaf *newleaf = NULL;
    int rc = 0;
    //遍历topic 将所有topic 放入hash table
    while(topics &&topics[topic_index]!= NULL)
    {
        topiclen = strlen(topics[topic_index]);
        HASH_FIND(hh,subhier->children,topics[topic_index],topiclen,branch);
        if(!branch)
        {
            //没有找到分支 topic生成节点, 没有找到表示是兄弟节点
            branch = sub_add_heir_entry(subhier,&subhier->children,topics[topic_index],topiclen);
            if(!branch) return SC_ERR_NOMEM;
        }
        subhier = branch;
        topic_index++;
    }

    //将context 添加到订阅链表末尾
    if(context && context->id)
    {
        rc = sub_add_leaf(context,options, &subhier->subs,&newleaf);
        if(rc>0)
            return rc;
    }
}

/*
func: 在订阅链表尾端添加订阅context 的节点 
*/
static int sub_add_leaf(struct sc_context *context, int options, struct sc_subleaf **head, struct sc_subleaf **newleaf)
{
    struct sc_subleaf *leaf;
    *newleaf = NULL;
    leaf = *head;
    while(leaf)
    {
        if(leaf->context && leaf->context->id && !strcmp(leaf->context->id,context->id)){
            //已存在
            return SC_ERR_SUB_EXISTS;
        }
        leaf = leaf->next;
    }
    leaf = calloc(1,sizeof(struct sc_subleaf));
    if(!leaf) return SC_ERR_NOMEM;

    leaf->context = context;

    DL_APPEND(*head,leaf);
    *newleaf = leaf;
    return SC_OK;

}


int sub__messages_queue(const char *source_id, const char *topic,struct sc_msg* msg)
{
    int rc = 0;
    int rc2 = 0;
    struct sc_subhier *subhier;
    char **split_topics = NULL;
    char *local_topic = NULL;
    if(sub_topic_tokenise(topic,&local_topic,&split_topics,NULL)) return 1; 

    HASH_FIND(hh,map_root,split_topics[0],strlen(split_topics[0]),subhier);
    if(subhier){
        rc = sub_search(subhier,split_topics,source_id,topic, msg);
    }
    free(split_topics);
    free(local_topic);
    return rc;
}
/*
单级通配符 +  可以匹配单个层级的主题。
多级通配符 #  匹配多级主题
*/
int sub_search(struct sc_subhier *sub, char **split_topics,const char *sourceid, const char* topic,struct sc_msg* msg)
{
    //嵌套查找，
    struct sc_subhier *branch;
    int rc = 0;
    bool have_subscribers = false;

    if(split_topics && split_topics[0])
    {
        HASH_FIND(hh,sub->children,split_topics[0],strlen(split_topics[0]),branch);
        if(branch){
            //找到split_topics[0] 对应的节点
            rc = sub_search(branch, &(split_topics[1]),sourceid,topic,msg);
            if(rc == SC_OK)
            {
                have_subscribers = true;
            }
            else if(rc!= SC_ERR_NO_SUBSCRIBERS)
            {
                return rc;
            }
            if(split_topics[1] == NULL)
            {
                //最后
                rc = sub_process(branch,sourceid,topic,msg);
                if(rc == SC_OK)
                {
                    have_subscribers = true;
                }
                else if( rc != SC_ERR_NO_SUBSCRIBERS)
                {
                    return rc;
                }
            }
        }  
              /* 检查 + 匹配情况 */
        HASH_FIND(hh,sub->children,"+",1,branch);
        if(branch){
            rc = sub_search(branch,&(split_topics[1]),sourceid,topic,msg);
             if(rc == SC_OK)
            {
                have_subscribers = true;
            }
            else if(rc!= SC_ERR_NO_SUBSCRIBERS)
            {
                return rc;
            }
            if(split_topics[1] == NULL)
            {
                //最后
                rc = sub_process(branch,sourceid,topic,msg);
                if(rc == SC_OK)
                {
                    have_subscribers = true;
                }
                else if( rc != SC_ERR_NO_SUBSCRIBERS)
                {
                    return rc;
                }
            }
        }

        /* 检查 # 匹配情况 */
        HASH_FIND(hh,sub->children,"#",1,branch);
        if(branch){
            rc = sub_process(branch,sourceid,topic,msg);
            if(rc == SC_OK)
            {
                have_subscribers = true;
            }
            else if( rc != SC_ERR_NO_SUBSCRIBERS)
            {
                return rc;
            }
        }        
    }
    if(have_subscribers)
    {
        return SC_OK;
    }else{
        return SC_ERR_NO_SUBSCRIBERS;
    }
}

static int sub_process(struct sc_subhier *hier, const char *source_id, const char *topic,struct sc_msg* msg)
{
    printf("process\n");
    int rc = 0;
    int rc2 = 0;
    struct sc_subleaf *leaf;
    leaf = hier->subs;
    //循环遍历订阅列表
    while(source_id && leaf){
        if(!leaf->context->id || !strcmp(leaf->context->id, source_id))
        {
            //id为空或者id 和source 相同，则跳过
            leaf = leaf->next;
            continue;
        }
        rc2 = subs__send(source_id,leaf,topic,msg);
        leaf = leaf->next;
    }
    if(hier->subs)
        return rc;
    else
        return SC_ERR_NO_SUBSCRIBERS;
}

/* 给每一个订阅context客户 发送消息 */
static int subs__send(const char *source_id,struct sc_subleaf *leaf, const char *topic,struct sc_msg* msg)
{
    if(leaf &&leaf->context->onwrite)
    {
        leaf->context->onwrite(source_id,msg->msg,msg->len,topic);
    }
}